package com.member.shop.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.member.common.utils.DateUtils;
import com.member.common.utils.StringUtils;
import com.member.shop.domain.*;
import com.member.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Description AlipayServiceImpl
 * @ClassName AlipayServiceImpl
 * @Date 2025/2/24 
 * @author luo.yun
 */
@Slf4j
@Service
public class AlipayServiceImpl implements IAlipayService {
    @Resource
    private ISysBizOrderService sysBizOrderService;
    @Resource
    private ISysBizUserService sysBizUserService;
    @Resource
    private ISysBizRechargeUserService sysBizRechargeUserService;
    @Resource
    private ISysBizUserSurplusDetailsService sysBizUserSurplusDetailsService;
    @Resource
    private ISysBizTenantService sysBizTenantService;

    @Value("${alipay.gateway-url}")
    private String gatewayUrl;

    @Value("${alipay.charset}")
    private String charset;

    @Value("${alipay.sign-type}")
    private String signType;

    @Value("${alipay.notify-url}")
    private String notifyUrl;

    @Override
    public String createOrder(Long tenantId, String orderNo, double amount, String body) throws AlipayApiException {
        SysBizTenant bizTenant = sysBizTenantService.getById(tenantId);
        if(bizTenant == null){
            log.error("createOrder bizTenant 未查询到支付宝配置数据");
            return "";
        }

        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setSubject(body);
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(String.valueOf(amount));
        model.setProductCode("QUICK_MSECURITY_PAY");
        model.setPassbackParams(tenantId.toString());//公用回传参数，如果请求时传递了该参数，则返回给商户时会回传该参数

        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
        ali_request.setBizModel(model);
        ali_request.setNotifyUrl(notifyUrl);// 回调地址

        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, bizTenant.getAliAppId(), bizTenant.getAliMerchantPrivateKey(),
                "json", charset, bizTenant.getAliAlipayPublicKey(), signType);

        AlipayTradeAppPayResponse ali_response = alipayClient.sdkExecute(ali_request);
        //就是orderString 可以直接给客户端请求，无需再做处理。
        return ali_response.getBody();
    }

    @Override
    public String createOrderByNotifyUrl(Long tenantId, String orderNo, double amount, String body, String url) throws AlipayApiException {
        SysBizTenant bizTenant = sysBizTenantService.getById(tenantId);
        if(bizTenant == null){
            log.error("createOrderByNotifyUrl 未查询到支付宝配置数据");
            return "";
        }

        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setSubject(body);
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(String.valueOf(amount));
        model.setProductCode("QUICK_MSECURITY_PAY");
        model.setPassbackParams(tenantId.toString());//公用回传参数，如果请求时传递了该参数，则返回给商户时会回传该参数

        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
        ali_request.setBizModel(model);
        ali_request.setNotifyUrl(url);// 回调地址

        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, bizTenant.getAliAppId(), bizTenant.getAliMerchantPrivateKey(),
                "json", charset, bizTenant.getAliAlipayPublicKey(), signType);

        AlipayTradeAppPayResponse ali_response = alipayClient.sdkExecute(ali_request);
        //就是orderString 可以直接给客户端请求，无需再做处理。
        return ali_response.getBody();
    }

    @Override
    public boolean notify(String tradeStatus, String orderNo, String tradeNo) {
        log.info("----- notify 回调参数,tradeStatus:{},orderNo:{},tradeNo:{}",tradeStatus,orderNo,tradeNo);
        if ("TRADE_FINISHED".equals(tradeStatus)
                || "TRADE_SUCCESS".equals(tradeStatus)) {
            // 支付成功，根据业务逻辑修改相应数据的状态
            SysBizOrder bizOrder = sysBizOrderService.getOne(new LambdaQueryWrapper<SysBizOrder>().eq(SysBizOrder::getPaymentId, orderNo));
            if(bizOrder == null){
                return false;
            }
            if(bizOrder.getStatus() == 10){
                bizOrder.setStatus(15);
                bizOrder.setPaymentStatus(1);
                bizOrder.setPaymentType(1);
                bizOrder.setPaymentTime(DateUtils.getNowDate());
                bizOrder.setTransactionId(tradeNo);//交易流水号
                sysBizOrderService.updateById(bizOrder);
            }

            return true;
        }
        return false;
    }

    @Override
    public boolean rsaCheckV1(HttpServletRequest request) {
        try {
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
                }
                params.put(name, valueStr);
            }

            SysBizTenant bizTenant = sysBizTenantService.getById(Long.parseLong(params.get("passback_params")));
            if(bizTenant == null){
                log.error("----------- rsaCheckV1 未查询到支付宝配置数据");
                return false;
            }

            boolean verifyResult = AlipaySignature.rsaCheckV1(params,
                    bizTenant.getAliAlipayPublicKey(),
                    charset,
                    signType);
            return verifyResult;
        } catch (AlipayApiException e) {
            log.error("verify sigin error, exception is:{}", e);
            return false;
        }
    }

    @Override
    public boolean notifyBySurplus(String tradeStatus, String orderNo, String tradeNo) {
        log.info("----- notify 回调参数,tradeStatus:{},orderNo:{},tradeNo:{}",tradeStatus,orderNo,tradeNo);
        List<SysBizRechargeUser> sysBizRechargeUsers = sysBizRechargeUserService.list(new LambdaQueryWrapper<SysBizRechargeUser>()
                .eq(SysBizRechargeUser::getPaymentNo, orderNo));
        SysBizRechargeUser sysBizRechargeUser = null;
        if (!org.springframework.util.CollectionUtils.isEmpty(sysBizRechargeUsers)) {
            sysBizRechargeUser = sysBizRechargeUsers.get(0);
        }
        if (sysBizRechargeUser == null) {
            log.info("{}:订单为空", tradeNo);
            return false;
        }
        if ("TRADE_FINISHED".equals(tradeStatus)
                || "TRADE_SUCCESS".equals(tradeStatus)) {
            if(sysBizRechargeUser.getStatus() == 10){
                Date nowDate = DateUtils.getNowDate();
                sysBizRechargeUser.setUpdateTime(nowDate);
                sysBizRechargeUser.setPayTime(nowDate);
                sysBizRechargeUser.setPaymentStatus(1);
                sysBizRechargeUser.setStatus(40);
                sysBizRechargeUser.setAuditStatus(1);
                sysBizRechargeUser.setTransactionId(tradeNo);

                // 修改用户充值金额
                SysBizUser sysBizUser = sysBizUserService.selectSysBizUserById(sysBizRechargeUser.getUserId());

                BigDecimal rechargeBalanceAfter = sysBizRechargeUser.getRechargeBalanceAfter();

                // 重新计算余额
                BigDecimal rechargeBalance = sysBizUser.getSurplus().add(sysBizRechargeUser.getRechargePrice());//.add(sysBizRechargeUser.getGivePrice())赠送金额先注释

                if (rechargeBalanceAfter.equals(rechargeBalance)) {
                    sysBizUser.setSurplus(rechargeBalance);
                    sysBizRechargeUser.setRechargeBalanceAfter(rechargeBalance);
                }else {
                   log.error("充值后的金额和充值记录数据不一致,rechargeBalanceAfter:{},rechargeBalanceAfter:{}",rechargeBalanceAfter,rechargeBalanceAfter);
                   return false;
                }

                sysBizRechargeUserService.updateById(sysBizRechargeUser);

                sysBizUserService.updateById(sysBizUser);

                // 新增充值记录
                sysBizUserSurplusDetailsService.save(SysBizUserSurplusDetails.builder()
                        .type(0)
                        .userId(sysBizUser.getId())
                        .tenantId(sysBizUser.getTenantId())
                        .rechargePrice(sysBizRechargeUser.getRechargePrice())
                        .price(sysBizRechargeUser.getRechargePrice())
                        .orderId(sysBizRechargeUser.getOrderId())
                        .createTime(nowDate)
                        .createBy(sysBizUser.getNickName())
                        .build());
            }
            return true;
        }

        return false;
    }

    @Override
    public String refund(Long tenantId, String orderNo, double amount, String refundReason, String tradeNo) {
        SysBizTenant bizTenant = sysBizTenantService.getById(tenantId);
        if(bizTenant == null){
            log.error("createOrderByNotifyUrl 未查询到支付宝配置数据");
            return "未查询到支付宝配置数据";
        }
        if(StringUtils.isBlank(orderNo)){
            return "订单编号不能为空";
        }
        if(amount <= 0){
            return "退款金额必须大于0";
        }

        AlipayTradeRefundModel model=new AlipayTradeRefundModel();
        // 商户订单号
        model.setOutTradeNo(orderNo);
        // 退款金额
        model.setRefundAmount(String.valueOf(amount));
        // 退款原因
        model.setRefundReason(refundReason);
        // 交易流水号
        model.setTradeNo(tradeNo);
        // 退款订单号(同一个订单可以分多次部分退款，当分多次时必传)
        model.setOutRequestNo(generateRefundNo());
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        alipayRequest.setBizModel(model);

        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, bizTenant.getAliAppId(), bizTenant.getAliMerchantPrivateKey(),
                "json", charset, bizTenant.getAliAlipayPublicKey(), signType);

        AlipayTradeRefundResponse alipayResponse = null;
        try {
            alipayResponse = alipayClient.execute(alipayRequest);
        } catch (AlipayApiException e) {
            log.error("订单退款失败，异常原因:{}", e);
        }

        if(alipayResponse != null){
            String code = alipayResponse.getCode();
            String subCode = alipayResponse.getSubCode();
            String subMsg = alipayResponse.getSubMsg();
            if("10000".equals(code)
                    && StringUtils.isBlank(subCode)
                    && StringUtils.isBlank(subMsg)){
                // 表示退款申请接受成功，结果通过退款查询接口查询
                // 修改用户订单状态为退款
                return "订单退款成功";
            }
            return subCode + ":" + subMsg;
        }
        return "订单退款失败";
    }

    /**
     * 生成唯一退款请求号（格式：REFUND_年月日时分秒_随机数）
     */
    private String generateRefundNo() {
        return String.format("REFUND_%tY%<tm%<td%<tH%<tM%<tS_%s",
                System.currentTimeMillis(),
                UUID.randomUUID().toString().substring(0, 6));
    }
}
